#include <iostream>
#include <sw/redis++/redis++.h>

void testStringCommands(sw::redis::Redis& redis)
{
    printf("String 系列命令:\n");
    printf("=============================================\n");
    {
        printf("SET 命令\n\n");
        redis.flushall();

        long long e = redis.exists("mykey");
        printf("redis < EXISTS mykey\n");
        printf("redis > %lld\n", e);

        bool b;
        b = redis.set("mykey", "Hello");
        printf("redis < SET mykey \"Hello\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        sw::redis::OptionalString v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        b = redis.set("mykey", "World", std::chrono::milliseconds(0), sw::redis::UpdateType::NOT_EXIST);
        printf("redis < SET mykey \"World\"NX\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        long long d;
        d = redis.del("mykey");
        printf("redis < DEL mykey\n");
        printf("redis > %lld\n", d);

        e = redis.exists("mykey");
        printf("redis < EXISTS mykey\n");
        printf("redis > %lld\n", e);

        b = redis.set("mykey", "World", std::chrono::milliseconds(0), sw::redis::UpdateType::EXIST);
        printf("redis < SET mykey \"World\"XX\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        b = redis.set("mykey", "World", std::chrono::milliseconds(0), sw::redis::UpdateType::NOT_EXIST);
        printf("redis < SET mykey \"World\"NX\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        b = redis.set("mykey", "Will expire in 10s", std::chrono::seconds(10));
        printf("redis < SET mykey \"Will expire in 10s\" EX 10\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        // for (int i = 10; i > 0; --i) {
        //     printf("Waiting %ds\n", i);
        //     std::this_thread::sleep_for(std::chrono::seconds(1));
        // }

        v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        printf("=============================================\n");
    }
    {
        printf("GET 命令\n\n");

        redis.flushdb();

        sw::redis::OptionalString v = redis.get("nonexisting");
        printf("redis < GET nonexisting\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        bool b = redis.set("mykey", "Hello");
        printf("redis < SET mykey \"Hello\"NX\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        v = redis.get("mykey");
        printf("redis < GET mykey\n");
        if (bool(v)) {
            printf("redis > \"%s\"\n", v->c_str());
        } else {
            printf("redis > (nil)\n");
        }

        long long d = redis.del("mykey");
        printf("redis < DEL mykey\n");
        printf("redis > %lld\n", d);

        long long e = redis.exists("mykey");
        printf("redis < EXISTS mykey\n");
        printf("redis > %lld\n", e);

        b = redis.hset("mykey", "name", "Bob");
        printf("redis < HSET mykey name Bob\n");
        printf("redis > %d\n", b ? 1 : 0);

        try {
            printf("redis < GET mykey\n");
            v = redis.get("mykey");
            if (bool(v)) {
                printf("redis > \"%s\"\n", v->c_str());
            } else {
                printf("redis > (nil)\n");
            }
        } catch (const sw::redis::ReplyError& exc) {
            printf("redis > %s\n", exc.what());
        }
        printf("=============================================\n");
    }
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // string commands
    testStringCommands(redis);
    return 0;
}
